package com.cqs.leetcode;


import java.util.Arrays;

/**
 * @author lixiaowen
 * @create 2019-12-18
 */
public class BitUtil {


    /**
     * 二进制码转十进制
     * @param binaryCode
     * @return
     */
    public static int binary2Decimal(int[] binaryCode){
        return Arrays.stream(binaryCode).boxed().reduce(0, (integer, integer2) -> integer * 2 + integer2);
    }



    /**
     * 转成二进制格式
     * @param n
     * @return
     */
    private static int[] toBinaryCode(int n) {
        //bins[0]表示最高为bins[31]为最低位
        int[] bins = new int[32];
        for (int i = 0; i < bins.length; ++i) {
            bins[i] = (n >> (bins.length - 1 - i)) & 0x1;
        }
        return bins;
    }




    static class GrayCode{

        /**
         * 格雷码转(对应的数字)化普通十进制
         * @param gray
         * @return
         */
        private static int gray2Decimal(int gray){
            //转成格雷码 方便位计算
            int[] grayCode = toBinaryCode(gray);
            int[] binaryCode = grayCode2binaryCode(grayCode);
            return binary2Decimal(binaryCode);
        }


        /**
         * 十进制自然数n对应的格雷
         * @param n
         * @return
         */
        public static int[] grayCode(int n){
            return grayCode(toBinaryCode(n));
        }

        /**
         * 二进制码转格雷码
         * @param binaryCode
         * @return
         */
        private static int[] grayCode(int[] binaryCode){
            int[] grayCode = new int[binaryCode.length];
            //grayCode[0]是最高位
            grayCode[0] = binaryCode[0];
            for (int i = 1; i <binaryCode.length ; i++) {
                grayCode[i] = binaryCode[i-1] ^ binaryCode[i];
            }
            return grayCode;
        }

        /**
         * 格林码转化为(自然数的)二进制
         * @param grayCode
         * @return
         */
        private static int[] grayCode2binaryCode(int[] grayCode){
            int[] binaryCode = new int[grayCode.length];
            binaryCode[0] = grayCode[0];
            for (int i = 1; i < grayCode.length ; i++) {
                binaryCode[i] = binaryCode[i-1] ^ grayCode[i];
            }
            return binaryCode;
        }



        public static void main(String[] args) {
            int n = 128;
            for (int source = 0; source < n; source++) {
                int[] binaryCode = toBinaryCode(source);
                int recover0 = binary2Decimal(binaryCode);
                int[] grayCode =grayCode(binaryCode);
                int[] binaryCode2 = grayCode2binaryCode(grayCode);
                int gray = binary2Decimal(grayCode);
                int gray2 = binary2Decimal(grayCode(source));
//                gray2 = binary2Decimal(grayCode(binaryCode));
                int recover = binary2Decimal(binaryCode2);

                System.out.println("source:" + source + "\t recover0: " + recover0 +"\t recover: " + recover + "\tgray:" + gray + "\tgray2:" + gray2  );
//                if (gray != gray2 || recover != source){
//                    throw new RuntimeException();
//                }


            }
        }
    }



}
